package com.kl.ccs;

import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch 是一个线程等待其他线程
 * CountDownLatch 的计数是减 1 直到 0
 * CountDownLatch 是一次性的
 */
@Slf4j
public class CountDownTest {

    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 现在设想一个场景，公司项目，线上出现了一个紧急 bug，被客户投诉，领导焦急的过来，想找人迅速的解决这个 bug
     * 那么，一个人解决肯定速度慢啊，于是叫来张三和李四，一起分工解决
     * 终于，当他们两个都做完了自己所需要做的任务之后，领导才可以答复客户，客户也就消气了（没办法啊，客户是上帝嘛）
     * 于是，我们可以设计一个 Worker 类来模拟单个人修复 bug 的过程，
     * 主线程就是领导，一直等待所有 Worker 任务执行结束，主线程才可以继续往下走
     * 优势：本来需要 5 秒完成的任务，两个人 3 秒就完成了
     */
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(2);
        Worker w1 = new Worker("张三", 2000, latch);
        Worker w2 = new Worker("李四", 3000, latch);
        w1.start();
        w2.start();

        long startTime = System.currentTimeMillis();
        // 调用 await()方法的线程主动阻塞等待被唤醒
        latch.await();
        log.info("bug全部解决，领导可以给客户交差了，任务总耗时：{}", System.currentTimeMillis() - startTime);
    }

    static class Worker extends Thread {
        String name;
        int workTime;
        CountDownLatch latch;

        public Worker(String name, int workTime, CountDownLatch latch) {
            this.name = name;
            this.workTime = workTime;
            this.latch = latch;
        }

        @Override
        public void run() {
            log.info("{}开始修复bug，当前时间：{}", name, sdf.format(new Date()));
            doWork();
            log.info("{}结束修复bug，当前时间：{}", name, sdf.format(new Date()));
            // 当前线程业务执行完就让记数减一
            latch.countDown();
        }

        private void doWork() {
            try {
                // 模拟工作耗时
                Thread.sleep(workTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}